function Node(num,edges){
	menode = this;
	menode.num = num;
	menode.edges = edges;
	menode.color = '#0064C7';
}

function Graph(){
	var me = this;
	
	this.nodes = [];
	this.nodeLimit = 5;
	
	this.nodeAdd = function(node){
		if(node == undefined){			
			this.nodes.push(me.nodeNext());
			this.nodelistDraw();
			this.nodebarlistDraw();
		} else {
			if(!me.nodeExist(node)){
				this.nodes.push(node);
				this.nodelistDraw();
				this.nodebarlistDraw();				
			}
		}
	};
	
	this.nodeDelete = function(t){
		var num = parseInt(t.children[1].innerHTML);
		var pos = -1;
		for(var i=0;i<me.nodes.length;i++){
			if(me.nodes[i].num == num){
				pos = i;				
			}
		}
		for(var i=0;i<me.nodes[pos].edges.length;i++){
			v = me.nodes[pos].num;
			e = me.nodes[pos].edges[i];
			me.nodeDeleteEdgeVE(e, v);
		}
		me.nodeDeletepos(pos);		
		this.nodelistDraw();
		this.nodebarlistDraw();
	};
	
	this.nodeDeletepos = function(pos){
		for(var i=pos;i<me.nodes.length;i++){
			me.nodes[i]=me.nodes[i+1]; 
		}
		me.nodes.pop();	
	};
	
	this.nodeAddEdge = function(nodenum, edge){
		if(nodenum != edge){			
			for(var i=0;i<me.nodes.length;i++){			
				if(me.nodes[i].num == nodenum && me.nodes[i].edges.indexOf(edge) == -1){
					this.nodes[i].edges.push(edge);
				}
			}
			me.nodebarlistDraw();
			me.graphDraw();
		}
	};
	
	this.nodeDeleteEdge = function(t){
		var e = parseInt(t.innerHTML);
		var v = parseInt(t.parentElement.parentElement.children[1].innerHTML);
		
		me.nodeDeleteEdgeVE(v, e);
		me.nodeDeleteEdgeVE(e, v);
		
		this.nodelistDraw();
		this.nodebarlistDraw();
	};
	
	this.nodeDeleteEdgeVE = function(v,e){
		var pos = -1;
		for(var i=0;i<me.nodes.length;i++){
			if(me.nodes[i].num==v){
				for(var j=0;j<me.nodes[i].edges.length;j++){
					if(me.nodes[i].edges[j]==e){
						pos = j;
					}
				}
				for(var j=pos;j<me.nodes[i].edges.length;j++){
					me.nodes[i].edges[j] = me.nodes[i].edges[j+1];
				}
				me.nodes[i].edges.pop();
				break;
			}			
		}
	};
	
	this.nodeNext = function(){		
		for(var i=0;i<(me.nodes.length+1);i++){
			n = new Node(i+1,[]);			
			if(!me.nodeExist(n)){				
				return n;
			}
		}
	};
	
	this.nodeExist = function(node){
		var exist = false;		
		for(var i=0; i < me.nodes.length; i++){			
			if(me.nodes[i].num == node.num ){
				exist = true;
				break;
			}
		}
		return exist;
	};
	
	this.nodesNumColor = function(){
		var nodes = [];
		for(var i=0;i<me.nodes.length;i++){
			nodes.push(me.nodes[i].num);
		}
		return nodes;
	};
	
	this.nodesEdges = function(){
		var edges = [];
		for(var i=0;i<me.nodes.length;i++){
			node = me.nodes[i];
			v = node.num;						
			for(var j=0;j<node.edges.length;j++){
					e = node.edges[j];
					edges.push([v,e]);			
			}
		}
		return edges;
	};
	
	this.nodeTemplate = function(num){
		return '<div class="circle" ondblclick="javascript:graph.nodeDelete(this);" draggable="true"><div class="outer-circle"></div><div class="middle-circle">'+num+'</div></div>';
	};
	
	this.nodebarTemplate = function(node){
		var html = '<div class="container"><div class="bar">';
		for(var i=0;i<node.edges.length;i++){
			html += '<p ondblclick="javascript:graph.nodeDeleteEdge(this)">' + node.edges[i] + '</p>';
		}		
		html += '</div><span>' + node.num + '</span></div>';
		return html;		
	};
	
	this.nodelistDraw = function(){
		var html = "";
		var nodelist = document.getElementsByClassName("nodegroup")[0];
		for(var i=0;i<this.nodes.length;i++){
			html += this.nodeTemplate(this.nodes[i].num);
		}
		if(document.getElementsByClassName('bar').length < (me.nodeLimit-1)){			
			html += '<div id="addNode" class="circle" onclick="javascript:graph.nodeAdd();"><div class="outer-circle"></div><div class="middle-circle">+</div></div>';
		}
		
		html += '<div class="clear"></clear>';
		nodelist.innerHTML = html;
	};
	
	this.nodebarlistDraw = function(){
		var html = "";
		var barlist = document.getElementById("containers");
		for(var i=0;i<this.nodes.length;i++){
			html += this.nodebarTemplate(this.nodes[i]);
		}
		html += '<div class="clear"></clear>';
		barlist.innerHTML = html;
		this.nodeEventsAdd();
		me.graphDraw();
	};

	this.nodeFindByNum = function(num){
		node = null;
		for(var i=0;i<this.nodes.length;i++){
			n = this.nodes[i];
			if(num = n){
				node = n;
				break;
			}
		}
		return node;
	};

	this.nodeEventsAdd = function(){
		sources = document.getElementsByClassName('circle');
		targets = document.getElementsByClassName('bar');
		for(var i=0; i < targets.length; i++){ 
			var source = sources[i];
			var target = targets[i];
			if (source.addEventListener) {  // all browsers except IE before version 9
				source.addEventListener ("dragstart", this.eventHandler, false);
				source.addEventListener ("draggesture", this.eventHandler, false);
				source.addEventListener ("drag", this.eventHandler, false);
				source.addEventListener ("dragend", this.eventHandler, false);
				target.addEventListener ("dragenter", this.eventHandler, false);
				target.addEventListener ("dragover", this.eventHandler, false);
				target.addEventListener ("dragleave", this.eventHandler, false);
				target.addEventListener ("dragexit", this.eventHandler, false);
				target.addEventListener ("drop", this.eventHandler, false);		
				target.addEventListener ("dragdrop", this.eventHandler, false);	
			}
		}		
	};
	
	this.eventHandler = function(event) {		
		if(event.type=="dragstart"){
			event.dataTransfer.setData('node',this.children[1].innerHTML);
		}
		if(event.type=="drop"){			
			var vertex = parseInt(event.target.parentElement.childNodes[1].innerHTML);
			var edge = parseInt(event.dataTransfer.getData('node'));			
			me.nodeAddEdge(vertex, edge);
			me.nodeAddEdge(edge, vertex);
		}
		if (event.type == "dragover") {
			if (event.preventDefault) {
				event.preventDefault ();
			}
		}
	};

    this.graphDraw = function(){
    	var G2 = jsnx.Graph();
    	
    	G2.add_nodes_from(me.nodesNumColor(), {color: '#0064C7'});
    	
    	G2.add_edges_from(me.nodesEdges());
    	
    	jsnx.draw(G2, {
    	    element: '#graph', 
    	    with_labels: true, 
    	    node_style: {
    	        fill: function(d) { 
    	            return d.data.color; 
    	        }
    	    }, 
    	    label_style: {fill: 'white' }
    	}, true);
    };
}

var nodesDefault = [new Node(1,[2]), new Node(2,[1])];

/* Init */
var graph = new Graph();

for(var i=0;i<nodesDefault.length;i++){
	graph.nodeAdd(nodesDefault[i]);
}